Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Android SR for ReactTextView and ReactEditText #569

Merged
merged 1 commit into from
Dec 21, 2023

Conversation

jonathanmos
Copy link
Member

@jonathanmos jonathanmos commented Dec 10, 2023

What does this PR do?

Implementation of Android Session Replay for ReactTextView and ReactEditText - "allow" only (masking requires a change on the Android sdk side before it can be implemented here)

Device
Screenshot_20231215_113049_Shopist2ReactNative
Screenshot_20231215_113100_Shopist2ReactNative
Screenshot_20231215_113105_Shopist2ReactNative

Replay
Screenshot 2023-12-15 at 11 27 07

Screenshot 2023-12-15 at 11 29 29 Screenshot 2023-12-15 at 11 25 51

Motivation

Necessary for Session Replay support for Android

Additional Notes

Anything else we should know when reviewing?

Review checklist (to be filled by reviewers)

  • Feature or bugfix MUST have appropriate tests
  • Make sure you discussed the feature or bugfix with the maintaining team in an Issue
  • Make sure each commit and the PR mention the Issue number (cf the CONTRIBUTING doc)
  • If this PR is auto-generated, please make sure also to manually update the code related to the change

@jonathanmos jonathanmos force-pushed the jmoskovich/rum-1817/record-android-text branch 2 times, most recently from b27e59a to a87b2e8 Compare December 10, 2023 23:12
@jonathanmos jonathanmos force-pushed the jmoskovich/rum-1817/record-android-text branch from 68aa3f2 to aef3116 Compare December 13, 2023 09:43
Copy link
Contributor

@louiszawadzki louiszawadzki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As it's hard to put extensive testing in place here, I believe we should rely on comments to make sure that if we want to revisit this code later we understand exactly what it does.

I've also suggested a few improvements.

Your screenshot also seems to be missing a few use cases, can you add all the examples on the screen?

@jonathanmos jonathanmos marked this pull request as ready for review December 18, 2023 08:28
@jonathanmos jonathanmos requested a review from a team as a code owner December 18, 2023 08:28
Comment on lines 69 to 79
MobileSegment.TextStyle(
family = "Serif",
size = forge.aPositiveLong(),
"#000000"
),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's extract this to the ForgeryFactory, maybe?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll extract this, but I'm a bit concerned that it duplicates logic in the native sdk. I'm wondering if we shouldn't change the visibility of the forgery factories there

@jonathanmos jonathanmos force-pushed the jmoskovich/rum-1817/record-android-text branch from 4f1fd12 to 8f2601e Compare December 18, 2023 10:15
louiszawadzki
louiszawadzki previously approved these changes Dec 19, 2023
Copy link
Contributor

@louiszawadzki louiszawadzki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me if @0xnm approves as well.

@jonathanmos jonathanmos requested a review from 0xnm December 19, 2023 16:12
val padding = textPosition?.padding
val alignment = resolveTextAlignment(view, textWireframe)

return textWireframe.copy(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do you create a copy here ? Couldn't we just resolve all the properties first and then after create the instance ?

Copy link
Member Author

@jonathanmos jonathanmos Dec 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll change to remove the copy in the drawable method and return pairs of values so we only copy the wireframe once. Copying the wireframe at least once is necessary (unless nothing changed in terms of properties), because the initial wireframe comes from the superclass map so it's either to do this or to duplicate the logic.

import java.lang.reflect.Field

internal class ReflectionUtils {
internal fun getDeclaredField(instance: Any, fieldName: String): Any? {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh wow...are we going to use reflection ? How many times is this code going to be called ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately yes, since we need the values from the React shadownode. It would be called multiple times for every view

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would test the performances of these methods and see how they could affect the frame rate. These methods are being called on the UIThread and it will be problematic. I would rather have less quality of the replays than affected performance.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mariusc83 performance benchmark is scheduled after this PR is merged. I agree that performance is more important than quality of replays.

Copy link
Member

@0xnm 0xnm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've left some final suggestions and then I think it is good to be merged.


internal companion object {
internal fun getLogger(): InternalLogger? {
return (Datadog.getInstance() as? FeatureSdkCore)?.internalLogger
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this is a best way to get a logger, because it has 2 problems:

  • it introduces nullability (it can be avoided if we get logger only once when feature is initialized, because it is guaranteed that core will be there at this point and its type is FeatureSdkCore)
  • each call to Datadog.getInstance introduces synchronization lock (not a big penalty, but still).

Normally in other features we are passing down the logger instance we got only once (or passing down SDK core instance), and anyway in the code of this module you have InternalLogger as constructor argument.

But it is not a blocker for me, if it works fine for you.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh this one is on me, I suggested this change.

I wasn't aware of the sync lock, let's watch how much of an impact this has in the perf benchmark.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably just peanuts and we shouldn't care about this penalty. But if we have some tracing data, it will be good.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've changed it back to passing the logger instance

0xnm
0xnm previously approved these changes Dec 20, 2023
Copy link
Member

@0xnm 0xnm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm!

@jonathanmos jonathanmos force-pushed the jmoskovich/rum-1817/record-android-text branch from 1d1850d to bdce711 Compare December 20, 2023 12:31
@jonathanmos jonathanmos force-pushed the jmoskovich/rum-1817/record-android-text branch from bdce711 to 7cc8400 Compare December 21, 2023 09:26
@jonathanmos jonathanmos merged commit 13c2ee0 into develop Dec 21, 2023
4 checks passed
@jonathanmos jonathanmos deleted the jmoskovich/rum-1817/record-android-text branch December 21, 2023 10:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants